<?php

namespace common\service;

use common\exception\LogicException;
use common\model\DelayOrderTaskModel;
use common\model\EntityEpisodeRelationModel;
use common\model\EntityModel;
use common\model\MediaModel;
use common\model\ModuleModel;
use common\model\PlanModel;
use common\model\ProjectMemberModel;
use common\model\ProjectModel;
use common\model\RepairOrderAffectedTaskModel;
use common\model\ReviewRequestModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\StepModel;
use common\model\TaskMemberModel;
use common\model\TaskModel;
use common\model\TaskRelationTagModel;
use common\model\TaskWorkOrderModel;
use common\model\UserModel;
use common\model\VersionModel;
use support\EntityTaskFilterParser;
use support\SingletonTrait;
use think\model\RelationModel;

class ProducerManageService
{
    // 单例模式工具
    use SingletonTrait;

    use EntityTaskFilterParser;

    protected $taskListQueryFields = [
        'task.id',
        'task.name',
        'task.step_type',
        "task.json",
        'task.step_id',
        'task.project_id',
        'task.executor_tenant_id',
        'task.executor_type',
        'task.tenant_id',
        'task.step_category_id',
        'task.end_time',
        'task.plan_end_time',
        'task.plan_start_time',
        'task.plan_delivery_time',
        'task.department_id',
        'task.assignee',
        'task.executor',
        'task.assign_status',
        'task.manual_man_hour',
        'task.delivery_time',
        'task.episode_id',
        'task.is_lock',
        'entity.id',
        'entity.initial_episode_code',
        'entity.showings_number',
        'entity.name',
        'entity.code',
        "entity.json",
        "entity.module_id",
        "entity.step_workflow_id",
    ];

    /**
     * 获取环节周期时间
     * @param $param
     * @param string $aloneTake
     * @return array
     */
    public function getSegmentCycleTime($param, $aloneTake = 'all')
    {
        $episodeEntityId = $param['filter']['entity_id'];
        $stepCategoryId = $param['filter']['step_category_id'] ?? 0;
        if ($stepCategoryId > 0) {
            $stepCategoryFilter = [
                'id' => $stepCategoryId
            ];
        }
        // 获取需要展示的分类环节
        $moduleIds = model(ModuleModel::class)->where(['code' => ['IN', 'asset,level,shot,design']])->column('id');
        $stepCategoryParentIds = model(StepCategoryModel::class)->where(['entity_id' => ['IN', $moduleIds], 'parent_id' => 0])->column('id');
        $stepCategoryFilter[] = ['parent_id' => ['IN', $stepCategoryParentIds]];
        $stepCategoryList = model(StepCategoryModel::class)->where($stepCategoryFilter)->select();
        $stepCategoryList = array_column($stepCategoryList, null, 'id');
        // 获取当前集中所有工序分类计划
        $episodeStepCategoryPlan = model(PlanModel::class)->where(['entity_id' => $episodeEntityId, 'type' => 'step_category'])->select();
        $episodeStepCategoryPlan = array_column($episodeStepCategoryPlan, null, 'step_category_id');
//        $episodePlan = model(PlanModel::class)->where(['project_id' => $projectId, 'entity_id' => $episodeEntityId, 'type' => 'episode'])->find();
//        if (empty($episodePlan)) {
//            throw new LogicException("episode plan not exist", ErrorCode::EPISODE_PLAN_NOT_EXIST);
//        }
        $stepCategoryList = array_map(function ($item) use ($episodeStepCategoryPlan, $episodeEntityId, &$min, &$max) {
            $item['row_type'] = "step_category";
            $item['entity_id'] = $episodeEntityId;
            if (isset($episodeStepCategoryPlan[$item['id']])) {
                $item['plan_id'] = $episodeStepCategoryPlan[$item['id']]["id"];
                $item['start_time'] = $episodeStepCategoryPlan[$item['id']]['start_time'];
                $item['end_time'] = $episodeStepCategoryPlan[$item['id']]['end_time'];
                $item['is_assign'] = 1; //以分配
            } else {  //填补集的默认的时间
                $item['start_time'] = 0;
                $item['end_time'] = 0;
                $item['is_assign'] = 0; //未分配
            }
            StepService::formatGanttItem($item, "startnoearlierthan");
            return $item;
        }, $stepCategoryList);
        if (!empty($stepCategoryList)) {
            $stepCategoryList = array_values($stepCategoryList);
        }
        $planData = StepService::formatStepCategoryPlanData($stepCategoryList, []);
        if ($aloneTake == 'all') {
            return $planData;
        }
        return $planData[$aloneTake];
    }

    /**
     * 获取环节任务列表
     * @param $param
     * @return array
     */
    public function getSegmentTaskList($param)
    {
        $episodeEntityId = $param['filter']['entity_id'];
        $stepCategoryId = $param['filter']['step_category_id'];
        $page = $param['page'] ?? [1, 20];
        $filterStatus = $param['filter']['status'] ?? "";
        $statusList = model(StatusModel::class)->select();
        $statusList = array_column($statusList, null, 'code');
        switch ($filterStatus) {
            case "not_final":
                $filter = [
                    '_string' => "json_unquote(json_extract(t.json, '$.task_status')) != {$statusList['final']['id']} and json_unquote(json_extract(t.json, '$.task_status')) != {$statusList['closed']['id']}"
                ];
                break;
            case "final":
                $filter = [
                    '_string' => "json_unquote(json_extract(t.json, '$.task_status')) = {$statusList['final']['id']}"
                ];
                break;
            case "closed":
                $filter = [
                    '_string' => "json_unquote(json_extract(t.json, '$.task_status')) = {$statusList['closed']['id']}"
                ];
                break;
            default:
                $filter = [];
        }
        $segmentTaskList = model(EntityEpisodeRelationModel::class)
            ->alias('er')
            ->field("t.id as task_id,t.name,json_unquote(json_extract(t.json, '$.task_status')) as task_status,t.plan_end_time,t.entity_id,json_unquote(json_extract(t.json, '$.task_is_overdue')) as task_is_overdue")
            ->join("task t on t.entity_id = er.entity_id")
            ->where(['er.episode_id' => $episodeEntityId, 't.step_type' => 'step_category', 't.step_category_id' => $stepCategoryId])
            ->where($filter)
            ->page($page[0], $page[1])
            ->group("er.entity_id")
            ->select();
        if (empty($segmentTaskList)) {
            return [];
        }
        // 状态列表
        $taskStatusIds = array_column($segmentTaskList, 'task_status');
        $statusList = model(StatusModel::class)->field('id,code,name')->where(['id' => ['IN', $taskStatusIds]])->select();
        $statusList = array_column($statusList, null, 'id');
        // 关联实体
        $segmentTaskRelateEntityIds = array_column($segmentTaskList, 'entity_id');
        $relateEntityList = model(EntityModel::class)->where(['id' => ['IN', $segmentTaskRelateEntityIds]])->select();
        $relateEntityList = array_column($relateEntityList, null, 'id');
        $segmentTaskList = array_map(function ($item) use ($relateEntityList, $statusList) {
            if (!empty($relateEntityList[$item['entity_id']])) {
                $item['entity_name'] = $relateEntityList[$item['entity_id']]['name'];
                $item['initial_episode_code'] = $relateEntityList[$item['entity_id']]['initial_episode_code'];
                $item['showings_number'] = $relateEntityList[$item['entity_id']]['showings_number'];
            }
            if (!empty($statusList[$item['task_status']])) {
                $item['task_status'] = $statusList[$item['task_status']];
            }
            $item['task_is_overdue'] = $item['task_is_overdue'] ?? 'no';
            return $item;
        }, $segmentTaskList);
        $taskOverdueList = array_column($segmentTaskList, 'task_is_overdue');
        array_multisort($taskOverdueList, SORT_DESC, $segmentTaskList);
        return $segmentTaskList;
    }

    /**
     * 获取环节任务详情列表
     * @param $param
     * @return array
     */
    public function getSegmentTaskDetailList($param)
    {
        $filter['task.step_type'] = 'step';
        $taskModel = model(TaskModel::class);
        $taskModel->field("task.id,task.name,task.plan_end_time,task.end_time,task.executor,json_unquote(json_extract(task.json, '$.task_status')) as task_status,json_unquote(json_extract(task.json, '$.task_is_overdue')) as task_is_overdue,task.entity_id,task.step_type,task.step_id");
        $isSelectStep = $param['filter']['select_step'] ?? false;
        if (isset($param['filter']['step_id'])) {
            $filter['task.step_id'] = $param['filter']['step_id'];
        }
        if (isset($param['filter']['step_category_id'])) {
            $filter['task.step_category_id'] = $param['filter']['step_category_id'];
        }
        if ($isSelectStep) {
            $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
            $statusList = model(StatusModel::class)->select();
            $statusList = array_column($statusList, null, 'code');
            $filterStatus = $param['filter']['status'] ?? "";
            switch ($filterStatus) {
                case "not_final":
                    $filter[] = [
                        '_string' => "json_unquote(json_extract(task.json, '$.task_status')) != {$statusList['final']['id']} and json_unquote(json_extract(task.json, '$.task_status')) != {$statusList['closed']['id']}"
                    ];
                    break;
                case "final":
                    $filter[] = [
                        '_string' => "json_unquote(json_extract(task.json, '$.task_status')) = {$statusList['final']['id']}"
                    ];
                    break;
                case "closed":
                    $filter[] = [
                        '_string' => "json_unquote(json_extract(task.json, '$.task_status')) = {$statusList['closed']['id']}"
                    ];
                    break;
            }
            $filter['eer.episode_id'] = $param['filter']['entity_id'];
            $taskModel->join("entity_episode_relation eer on eer.entity_id = task.entity_id");
            $taskModel->group("task.id");
            $taskModel->page($page[0], $page[1]);
        } else {
            $filter['task.entity_id'] = $param['filter']['entity_id'];
        }
        $taskList = $taskModel->where($filter)->select();
        if (empty($taskList)) {
            return [];
        }
        // 任务执行人
        $taskExecutorIds = array_column($taskList, 'executor');
        $taskExecutorList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', $taskExecutorIds]])->select();
        $taskExecutorList = array_column($taskExecutorList, null, 'id');
        // 任务状态
        $taskStatusIds = array_column($taskList, 'task_status');
        $statusList = model(StatusModel::class)->where(['id' => ['IN', $taskStatusIds]])->select();
        $statusList = array_column($statusList, null, 'id');
        // 任务实体
        $taskEntityIds = array_column($taskList, 'entity_id');
        $entityList = model(EntityModel::class)->field('id,name,initial_episode_code,showings_number')->where(['id' => ['IN', $taskEntityIds]])->select();
        $entityList = array_column($entityList, null, 'id');
        $taskList = array_map(function ($item) use ($taskExecutorList, $statusList, $entityList) {
            if (!empty($taskExecutorList[$item['executor']])) {
                $item['executor'] = $taskExecutorList[$item['executor']]['name'];
            }
            if (!empty($statusList[$item['task_status']])) {
                $item['status'] = $statusList[$item['task_status']];
            }
            if (!empty($entityList[$item['entity_id']])) {
                $item['entity'] = $entityList[$item['entity_id']];
            }
            $item['task_is_overdue'] = $item['task_is_overdue'] ?? 'no';
            return $item;
        }, $taskList);
        $taskOverdueList = array_column($taskList, 'task_is_overdue');
        array_multisort($taskOverdueList, SORT_DESC, $taskList);
        return $taskList;
    }

    /**
     * 获取环节返修统计
     * @param $param
     * @return array
     */
    public function getSegmentRepairCount($param)
    {
        $filter['roat.repair_status'] = $param['filter']['repair_status'] ?? 'no';
        if (!empty($param['filter']['select_step'])) {
            $filter['t.step_id'] = $param['filter']['step_id'];
        } else {
            $filter['t.step_category_id'] = $param['filter']['step_category_id'];
        }
        $entityQuery = model(EntityEpisodeRelationModel::class)->field("distinct entity_id")->where(['episode_id' => $param['filter']['entity_id']])->buildSql();
        return model(RepairOrderAffectedTaskModel::class)
            ->alias("roat")
            ->field("tro.report_type,count(distinct t.id) as count")
            ->join("task_repair_order tro on tro.id = roat.task_repair_order_id")
            ->join("task t on t.id = roat.task_id")
            ->join($entityQuery . "as er on er.entity_id = t.entity_id")
            ->where($filter)
            ->group("tro.report_type")
            ->select();
    }

    /**
     * 获取环节返修工序详细列表
     * @param $param
     * @return array
     */
    public function getSegmentRepairDetailList($param)
    {
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $isSelectStep = $param['filter']['select_step'] ?? false;
        if ($isSelectStep) {
            $filter['t.step_id'] = $param['filter']['step_id'];
        } else {
            $filter['t.step_category_id'] = $param['filter']['step_category_id'];
        }
        $episodeEntityId = $param['filter']['entity_id'];
        $episodeRelateEntityQuery = model(EntityEpisodeRelationModel::class)
            ->field("distinct entity_id")
            ->where(['episode_id' => $episodeEntityId])
            ->buildSql();
        $filter['tro.report_type'] = $param['filter']['repair_type'];
        $filter['roat.repair_status'] = $param['filter']['repair_status'] ?? 'no';
        $taskRepairList = model(RepairOrderAffectedTaskModel::class)
            ->alias("roat")
            ->field("t.name,t.plan_end_time,t.entity_id,tro.step_category_id,tro.step_id,t.executor,t.id as task_id")
            ->join("task_repair_order tro on tro.id = roat.task_repair_order_id")
            ->join("task t on t.id = roat.task_id")
            ->join($episodeRelateEntityQuery . "as er on er.entity_id = t.entity_id")
            ->where($filter)
            ->page($page[0], $page[1])
            ->group("t.id")
            ->select();
        if (empty($taskRepairList)) {
            return [];
        }
        $taskStepList = [];
        $taskStepCategoryList = [];
        // 获取工序或者环节列表
        if ($isSelectStep) {
            $taskStepIds = array_column($taskRepairList, 'step_id');
            $taskStepList = model(StepModel::class)->where(['id' => ['IN', $taskStepIds]])->select();
            $taskStepList = array_column($taskStepList, null, 'id');
        } else {
            $taskStepCategoryIds = array_column($taskRepairList, 'step_category_id');
            $taskStepCategoryList = model(StepCategoryModel::class)->where(['id' => ['IN', $taskStepCategoryIds]])->select();
            $taskStepCategoryList = array_column($taskStepCategoryList, null, 'id');
        }
        // 任务执行人
        $taskExecutorIds = array_column($taskRepairList, 'executor');
        $taskExecutorList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', $taskExecutorIds]])->select();
        $taskExecutorList = array_column($taskExecutorList, null, 'id');
        // 实体
        $taskEntityIds = array_column($taskRepairList, 'entity_id');
        $entityList = model(EntityModel::class)->field("id,name,initial_episode_code,showings_number")->where(['id' => ['IN', $taskEntityIds]])->select();
        $entityList = array_column($entityList, null, 'id');
        return array_map(function ($item) use ($taskStepCategoryList, $taskStepList, $entityList, $taskExecutorList) {
            if ($taskStepCategoryList && !empty($taskStepCategoryList[$item['step_category_id']])) {
                $item['step_category_name'] = $taskStepCategoryList[$item['step_category_id']]['name'];
            }
            if ($taskStepList && !empty($taskStepList[$item['step_id']])) {
                $item['step_name'] = $taskStepList[$item['step_id']]['name'];
            }
            if (!empty($entityList[$item['entity_id']])) {
                $item['entity'] = $entityList[$item['entity_id']];
            }
            if (!empty($taskExecutorList[$item['executor']])) {
                $item['executor'] = $taskExecutorList[$item['executor']]['name'];
            }
            return $item;
        }, $taskRepairList);
    }

    /**
     * 获取环节工单列表
     * @param $filter
     * @param $param
     * @return void
     */
    public function getSegmentWorkOrderList(&$filter, $param)
    {
        $isSelectStep = $param['select_step'] ?? false;
        if ($isSelectStep) {
            $manageFilter['two.step_id'] = $param['step_id'];
        } else {
            $manageFilter['two.step_category_id'] = $param['step_category_id'];
        }
        $manageFilter['er.episode_id'] = $param['entity_id'];
        $manageFilter['two.status'] = $param['task_work_order_status'];
        $taskWorkOrderList = model(EntityEpisodeRelationModel::class)
            ->alias("er")
            ->field("two.*")
            ->join("task_work_order two on two.entity_id = er.entity_id")
            ->where($manageFilter)
            ->select();
        $taskWorkOrderIds = array_column($taskWorkOrderList, 'id');
        $filter['task_work_order.id'] = ['IN', implode(',', $taskWorkOrderIds)];
    }

    /**
     * 获得一个任务列表查询对象
     * @param $tableList
     * @return RelationModel
     */
    public function getTaskListQuery($tableList, $joinedList = [])
    {
        $q = model(TaskModel::class);
        $joined = $joinedList;

        foreach ($tableList as $table) {
            if (in_array($table, $joined)) {
                continue;
            }
            $joined[] = $table;
            switch ($table) {
                case 'module':
                    $q = $q->join('module on module.id = task.entity_module_id', 'LEFT');
                    break;
                case 'entity':
                    $q = $q->join('entity on entity.id = task.entity_id', 'LEFT');
                    break;
                case 'task_work_order_temp':
                    $q = $q->join('(select task_id from task_work_order where status = ' . TaskWorkOrderModel::STATUS_UNTREATED . ' group by task_id) task_work_order_temp on task_work_order_temp.task_id = task.id', 'LEFT');
                    break;
                case 'task_member':
                    $q = $q->join('task_member on task_member.task_id = task.id', 'LEFT');
                    break;
                case 'plan':
                    $q = $q->join('plan on plan.task_id = task.id', 'LEFT');
                    break;
                case 'r_episode':
                    $q = $q->join("(select * from task_relation_tag where link_module_code in ('episode')) r_episode on r_episode.task_id = task.id", 'LEFT');
                    break;
                case 'r_step_category':
                    $q = $q->join("(select * from task_relation_tag where link_module_code in ('step_category','show_step_category')) r_step_category on r_step_category.task_id = task.id", 'LEFT');
                    break;
                case 'version':
                    $q = $q->join("version on task.id = version.link_id and version.module_id = " . module_by_code('version')['id'], 'LEFT');
                    break;
            }
        }
        return $q;
    }

    /**
     * 制片管理任务列表
     * @param $param
     * @param $tenantId
     * @param $extraFilter
     * @param $needTotal
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function taskList($param, $tenantId, $extraFilter = [], $needTotal = true)
    {
        $total = 0;
        // Check if the merge step is the last task
        $isMergeStepLastTask = $param['is_merge_step_last_task'] ?? 'no';
        $isMergeStepLastTask = $isMergeStepLastTask === 'yes';
        // If tenant id is greater than 0, set the filter for the task list
        if ($tenantId > 0) {
            $param['filter']['task.tenant_id'] = $tenantId;
        }
        $nodeMode = (($param['node_mode'] ?? 'no') === 'yes' && isset($param['filter']['task.id']));

        $sourceFilter = $param['filter'] ?? [];
        // Build the task list filter
        $filter = $this->buildTaskListFilter($param, $nodeMode);
        // Get the table list
        $tableList = $this->tableList;
        // Get the default closed status
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        // Set the page and order
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $order = $param['order'] ?? 'task.plan_end_time ASC';
        // Add the filter for the task type and task status
        $filter[] = [
            'task.step_type' => ['NOT IN', [TaskModel::STEP_TYPE_STEP_CATEGORY]],
            "task.json->>'$.task_status'" => ['NEQ', $closedStatus['id']],
        ];

        // 新增需求
        if (!empty($param['need_change_type']) && $param['need_change_type'] == 'append') {

            $projectId = $param['filter']['project_id'] ?? 0;
            $stepCategoryId = $param['step_category_id'] ?? '';
            $departmentId = $param['department_id'] ?? 0;
            $moduleCode = $param['filter']['module_code'] ?? '';
            $startTime = $param['start_time'] ?? 0;
            $endTime = $param['end_time'] ?? 0;
            $appendReviewFeedbackTaskIds = DemandOrderService::getInstance()->appendReviewReedBackIds($projectId, $stepCategoryId, $departmentId, $moduleCode, $startTime, $endTime, 'task');
            if (empty($appendReviewFeedbackTaskIds)) {
                return [];
            }
            $filter[] = ['task.id' => ['IN', $appendReviewFeedbackTaskIds]];
        }
        // 新增-返修
        if (!empty($param['need_change_type']) && $param['need_change_type'] == 'repair') {

            $projectId = $param['filter']['project_id'] ?? 0;
            $stepCategoryId = $param['step_category_id'] ?? '';
            $departmentId = $param['department_id'] ?? 0;
            $moduleCode = $param['filter']['module_code'] ?? '';
            $startTime = $param['start_time'] ?? 0;
            $endTime = $param['end_time'] ?? 0;
            $appendReviewFeedbackTaskIds = DemandOrderService::getInstance()->appendRepairReedBackIds($projectId, $stepCategoryId, $departmentId, $moduleCode, $startTime, $endTime, 'task');
            if (empty($appendReviewFeedbackTaskIds)) {
                return [];
            }
            $filter[] = ['task.id' => ['IN', $appendReviewFeedbackTaskIds]];
        }
        // 新增-废除
        if (!empty($param['need_change_type']) && $param['need_change_type'] == 'abo') {

            $projectId = $param['filter']['project_id'] ?? 0;
            $stepCategoryId = $param['step_category_id'] ?? '';
            $departmentId = $param['department_id'] ?? 0;
            $moduleCode = $param['filter']['module_code'] ?? '';
            $startTime = $param['start_time'] ?? 0;
            $endTime = $param['end_time'] ?? 0;
            $appendReviewFeedbackTaskIds = DemandOrderService::getInstance()->aboRepairReedBackIds($projectId, $stepCategoryId, $departmentId, $moduleCode, $startTime, $endTime, 'task');
            if (empty($appendReviewFeedbackTaskIds)) {
                return [];
            }
            $filter[] = ['task.id' => ['IN', $appendReviewFeedbackTaskIds]];
        }
        // 返修情况
        if (!empty($param['repair_info_type'])) {
            $repairInfoParam['project_id'] = $param['filter']['project_id'] ?? 0;
            $repairInfoParam['step_category_id'] = $param['step_category_id'];
            $repairInfoParam['start_time'] = $param['start_time'];
            $repairInfoParam['end_time'] = $param['end_time'];
            $repairInfoParam['data_type'] = 'list';
            $repairTaskInfo = teamones_request('teamones-olap-sr', 'task_repair/get_effected_task_info', $repairInfoParam)['data'];
            // 上游返修
            if ($param['repair_info_type'] == 'upstream') {
                if (empty($repairTaskInfo['upstream_step_category_task_list'])) {
                    return [];
                }
                $upstreamTaskIds = $repairTaskInfo['upstream_step_category_task_list'];
                $filter[] = ['task.id' => ['IN', $upstreamTaskIds]];

            }
            // 本环节返修
            if ($param['repair_info_type'] == 'self') {
                if (empty($repairTaskInfo['step_category_task_list'])) {
                    return [];
                }
                $nowStepCategoryTaskIds = $repairTaskInfo['step_category_task_list'];
                $filter[] = ['task.id' => ['IN', $nowStepCategoryTaskIds]];
            }
        }

        // If need total, get the total count of the tasks
        if ($needTotal) {
            $total = $this->getTaskListTotal($tableList, $filter, $extraFilter, $sourceFilter);
        }

        // Set the task filter
        $taskFilter = [];
        // If the merge step is the last task, get the entity step list
        if ($isMergeStepLastTask) {
            $entityStepList = $this->getTaskListQuery($tableList)
                ->where($filter)
                ->where($extraFilter)
                ->page($page[0], $page[1])
                ->field('task.entity_id,max(task.step_id) step_id')
                ->group('task.entity_id')
                ->order($order)
                ->select();
            if (empty($entityStepList)) {
                if ($needTotal) {
                    return [
                        'total' => $total,
                        'rows' => [],
                    ];
                }
                return [];
            }
            // Set the entity step filter
            $entityStepFilter = [];
            foreach ($entityStepList as $entityStepItem) {
                $entityStepFilter[] = ['entity.id' => $entityStepItem['entity_id'], 'task.step_id' => $entityStepItem['step_id']];
            }
            if (count($entityStepFilter) === 1) {
                $taskFilter = $entityStepFilter[0];
            } else {
                $taskFilter = $entityStepFilter;
                $taskFilter['_logic'] = 'OR';
            }
        }
        if (!$isMergeStepLastTask) {

            // Get the task id list
            $taskIdList = $this->getTaskListIdList($tableList, $filter, $extraFilter, $sourceFilter, $page, $order);
            if (empty($taskIdList)) {
                if ($needTotal) {
                    return [
                        'total' => $total,
                        'rows' => [],
                    ];
                }
                return [];
            }
            // Set the task filter
            $taskFilter = ['task.id' => ['IN', array_column($taskIdList, 'id')]];
        }
        $rows = $this->getTaskListData($taskFilter, $order, $param['version_only_published'] ?? false);
        if ($needTotal) {
            $rows = [
                'rows' => $rows,
                'total' => $total,
            ];
        }
        return $rows;
    }

    /**
     * 制片管理任务列表数据处理
     * @param $taskFilter
     * @param $order
     * @param $versionOnlyPublished
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function getTaskListData($taskFilter, $order, $versionOnlyPublished)
    {
        $rows = model(TaskModel::class)
            ->join('entity on task.entity_id = entity.id', 'LEFT')
            ->join('module on module.id = entity.module_id', 'LEFT')
            ->where($taskFilter)
            ->field(build_complex_query_fields($this->taskListQueryFields, '__'))
            ->order($order)
            ->select();
        $taskIdList = array_column($rows, 'task__id');
        // query task version count
        $taskCountVersionNumber = model(VersionModel::class)
            ->where(['module_id' => module_by_code('task')['id'], 'link_id' => ['IN', $taskIdList]])
            ->group('link_id')
            ->field('link_id,count(id) as count')
            ->select();
        $taskCountVersionNumber = array_column($taskCountVersionNumber, 'count', 'link_id');
        // query task episode tag
        $taskEpisodeTags = model(TaskRelationTagModel::class)->where(['task_id' => ['IN', implode(',', $taskIdList)], 'link_module_code' => 'episode'])->select();
        // query task episode info
        $tagEpisodeList = [];
        if (!empty($taskEpisodeTags)) {
            $episodeIdList = array_column($taskEpisodeTags, 'link_id', 'link_id');
            $tagEpisodeList = EpisodeService::getInstance()->selectEpisodeMap(['id' => ['IN', $episodeIdList]], 'id,name,code,"episode" link_module_code', 'id', null);
        }
        $taskEpisodeTagsGroupedByTaskId = array_group_by($taskEpisodeTags, 'task_id');
        // query task attr info
        $taskAttr = InsideTaskReviewWorkflowService::getInstance()->getMultipleTaskAttr($taskIdList);
        // query task max version info
        $maxVersionList = VersionService::getInstance()->getTaskMaxVersionInfo($taskIdList, '*', $versionOnlyPublished === 'yes');
        $maxVersionList = array_column($maxVersionList, null, 'link_id');
        // separate data sub table primary key
        $statusIdList = [];
        $stepCategoryIdList = [];
        $stepIdList = [];
        $taskList = [];
        $userIdList = [];
        $todoTaskIdList = [];
        $projectIdList = [];
        $taskVersionMediaIdList = [];
        $taskIds = [];
        $episodeIds = [];
        foreach ($rows as $rowIndex => &$row) {
            $row = separate_complex_query_data($row, '__');
            $taskId = $row['task']['id'];
            $taskIds[] = $row['task']['id'];
            $row['version'] = $maxVersionList[$taskId] ?? null;
            $row['version_media_id'] = [];
            if (!empty($row['version']['json'])) {
                $versionJson = json_decode((string)$row['version']['json'], true);
                if (!empty($versionJson['version_media'])) {
                    $row['version_media_id'] = explode(',', $versionJson['version_media']);
                    foreach ($row['version_media_id'] as $mediaId) {
                        $taskVersionMediaIdList[$mediaId] = $mediaId;
                    }
                }
            }
            $row['task']['task_attr'] = $taskAttr[$taskId] ?? '';
            $row['task']['is_lock'] = $row['task']['is_lock'] ?? 'no';
            $projectIdList[$row['task']['project_id']] = $row['task']['project_id'];
            $stepIdList[$row['task']['step_id']] = $row['task']['step_id'];
            $stepCategoryIdList[$row['task']['step_category_id']] = $row['task']['step_category_id'];
            if ($row['entity']['module_id'] > 0) {
                $row['entity'] = array_merge(get_no_prefix_json_fields($row['entity']['json'], module_by_id($row['entity']['module_id'])['code']), $row['entity']);
                $row['entity']['is_outsourcing'] = !empty($row['entity']['is_outsource']) && $row['entity']['is_outsource'] === 'yes';
            }
            $row['task'] = array_merge(get_no_prefix_json_fields($row['task']['json'], 'task'), $row['task']);
            if (!in_array($row['task']['status'], $statusIdList)) {
                $statusIdList[] = $row['task']['status'];
            }
            $row['task']['review_number'] = $taskCountVersionNumber[$taskId] ?? 0;
            $row['task']['is_outsourcing'] = $row['task']['executor_tenant_id'] > 0 && $row['task']['executor_tenant_id'] != $row['task']['tenant_id'];
            if ($row['task']['step_type'] == TaskModel::STEP_TYPE_STEP) {
                if ($row['task']['executor'] > 0) {
                    $userIdList[$row['task']['executor']] = $row['task']['executor'];
                }
                if ($row['task']['assignee'] > 0) {
                    $userIdList[$row['task']['assignee']] = $row['task']['assignee'];
                }
                $episodeIds[$row['task']['episode_id']] = $row['task']['episode_id'];
            } else {
                $todoTaskIdList[] = $taskId;
            }
            $taskList[] = &$rows[$rowIndex];
        }
        // 查询延期信息
        $taskDelayMap = ReviewTaskDelayService::getInstance()->taskDelayInfo($taskIds);
        unset($projectIdList[0]);
        // 处理图片
        $mediaList = [];
        if (!empty($taskVersionMediaIdList)) {
            $mediaList = model(MediaModel::class)
                ->where([
                    'id' => ["IN", $taskVersionMediaIdList]
                ])->field('id,thumb,param')->cache(C('database.default_query_cache_time'))
                ->select();
            $mediaList = array_map(function ($mediaItem) {
                $mediaItem['param'] = json_decode($mediaItem['param'], true);
                return $mediaItem;
            }, $mediaList);
            $mediaList = array_column($mediaList, null, "id");
        }

        // Get the list of status, steps, and step categories by the given ids
        $statusList = [];
        if (!empty($statusIdList)) {
            $statusList = StatusService::getInstance()->getList(['id' => ['IN', $statusIdList]], 'id,name,code,color');
            $statusList = array_column($statusList, null, 'id');
        }
        $stepList = [];
        if (!empty($stepIdList)) {
            $stepList = StepService::getInstance()->getSteps(['id' => ['IN', implode(',', $stepIdList)]], 'id,name,code');
            $stepList = array_column($stepList, null, 'id');
        }
        $stepCategoryList = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryList = StepCategoryService::getInstance()->getList(['id' => ['IN', implode(',', $stepCategoryIdList)]], 'id,name,code');
            $stepCategoryList = array_column($stepCategoryList, null, 'id');
        }
        //排期时间查询
        $planTimeMap = PlanService::getInstance()->getEpisodeStepCategoryPlanObject($episodeIds, $stepCategoryIdList);
        // 待办
        $taskMemberList = [];
        $todoPlanObject = [];
        if (!empty($todoTaskIdList)) {
            // 计划交付时间查询
            $todoPlanObject = TodoService::getInstance()->getPlanDeliveryTime($todoTaskIdList);
            $taskMemberList = model(TaskMemberModel::class)
                ->where(['task_id' => ['IN', implode(',', $todoTaskIdList)]])
                ->where(['partner' => ['GT', 0]])
                ->select();
            foreach ($taskMemberList as $taskMember) {
                if ($taskMember['user_id'] > 0) {
                    $userIdList[$taskMember['user_id']] = $taskMember['user_id'];
                }
                if ($taskMember['partner'] > 0) {
                    $userIdList[$taskMember['partner']] = $taskMember['partner'];
                }
            }
            $taskMemberList = array_group_by($taskMemberList, 'task_id');
        }
        // 用户
        $userList = [];
        if (!empty($userIdList)) {
            $userList = model(UserModel::class)
                ->where(['id' => ['IN', implode(',', $userIdList)]])
                ->field('id,name,avatar')
                ->select();
            $userList = array_column($userList, null, 'id');
        }
        // 项目
        $projectList = [];
        if (!empty($projectIdList)) {
            $projectList = model(ProjectModel::class)
                ->where(['id' => ['IN', implode(',', $projectIdList)]])
                ->field('id,name,code,work_dir')
                ->select();
            $projectList = array_column($projectList, null, 'id');
        }
        $this->queryTaskAbnormalDetail($taskList);
        foreach ($rows as &$row) {
            $row['step'] = $stepList[$row['task']['step_id']] ?? null;
            $row['step_category'] = $stepCategoryList[$row['task']['step_category_id']] ?? null;
            $row['task_status'] = $statusList[$row['task']['status']] ?? null;
            $row['project'] = $projectList[$row['task']['project_id']] ?? null;
            $row['task_relation_tag_list'] = $taskEpisodeTagsGroupedByTaskId[$row['task']['id']] ?? [];
            $row['task_relation_tag'] = [];
            $row['delivery_plan'] = null;
            $row['assignee'] = null;
            unset($row['entity']['json'], $row['task']['json']);
            // Check if step type is STEP
            if ($row['task']['step_type'] == TaskModel::STEP_TYPE_STEP) {
                $row['task_member_list'] = [[
                    'id' => $row['task']['id'],
                    'status' => $row['task']['status'] != 7 ? 1 : 7,
                    'user_info' => $userList[$row['task']['executor']] ?? null,
                    'type' => 'executor',
                ]];
                $row['assignee'] = $userList[$row['task']['assignee']] ?? null;
                $row['delivery_plan'] = $planTimeMap[$row['task']['episode_id']][$row['task']['step_category_id']] ?? null;
                //存在属性排期
                if (!empty($row['entity']['category']) && !empty($planTimeMap[$row['task']['episode_id']][$row['task']['step_category_id'].'#'.$row['entity']['category']])) {
                    $row['delivery_plan'] = $planTimeMap[$row['task']['episode_id']][$row['task']['step_category_id'].'#'.$row['entity']['category']] ?? null;
                }
            } else {
                $row['delivery_plan'] = $todoPlanObject[$row['task']['id']] ?? null;
                // Loop through task relation tags
                foreach ($row['task_relation_tag_list'] as $taskRelationTag) {
                    if (isset($tagEpisodeList[$taskRelationTag['link_id']])) {
                        $row['task_relation_tag'][] = $tagEpisodeList[$taskRelationTag['link_id']];
                    }
                }
                $row['task_member_list'] = $taskMemberList[$row['task']['id']] ?? [];
                // Loop through task members
                foreach ($row['task_member_list'] as &$taskMember) {
                    if ($taskMember['partner'] > 0) {
                        $taskMember['user_info'] = $userList[$taskMember['partner']] ?? null;
                    }
                    $taskMember['type'] = $taskMember['user_id'] > 0 ? 'executor' : 'partner';
                }
            }
            $row['version']['version_media'] = [];
            // Loop through version media ids
            foreach ($row['version_media_id'] as $mediaId) {
                if (isset($mediaList[$mediaId])) {
                    $row['version']['version_media'][] = $mediaList[$mediaId];
                }
            }
            $row['task']['is_task_delay'] = !empty($taskDelayMap[$row['task']['id']]);
            // Check if task delay map is not empty
            if (!empty($taskDelayMap[$row['task']['id']])) {
                $row['task']['task_delay_time'] = $taskDelayMap[$row['task']['id']]['task_delay_time'];
                $row['task']['task_delay_reason'] = $taskDelayMap[$row['task']['id']]['task_delay_reason'];
            }
        }
        return $rows;
    }

    /**
     * 构建任务列表筛选条件
     * @param $param
     * @return array
     */
    private function buildTaskListFilter($param, $nodeMode = false)
    {
        $res = $param['filter'] ?? [];
        $executor = $param['filter']['executor'] ?? null;
        $taskStepType = $param['filter']['task_step_type'] ?? null;

        $specialRoleFilter = $res['special_role_filter'] ?? null;
        unset($res['executor'], $res['task_step_type']);
        $res = $this->parseMultipleEntityTaskFilter($res, $nodeMode);
        if (!empty($specialRoleFilter)) {
            switch ($specialRoleFilter) {
                case 'artist':
                    $taskMemberParentUserId = request()->getUserId();
                    if (!empty($executor)) { // 查询指定执行人
                        $taskMemberParentUserId = $executor;
                    }
                    if (!empty($taskStepType)) {
                        $res[] = [
                            'task.step_type' => $taskStepType
                        ];
                        $this->appendTableList('task');
                    }
                    $res[] = [
                        'task_member.user_id' => $taskMemberParentUserId
                    ];
                    $this->appendTableList('task_member');
                    break;
                case 'headman':
                    $departmentList = TaskAssignService::getInstance()->getDepartmentManagerDepartmentList();
                    if (empty($departmentList)) {
                        $res[] = ['task.id' => 0];
                    } else {
                        $departmentIdList = array_column($departmentList, 'id');
                        $res[] = ['task.department_id' => ['IN', $departmentIdList]];
                    }
                    $this->appendTableList('task');
                    break;
                case TaskService::DIRECTOR_CODE:
                    if (!empty($param['filter']['task.project_id'])) {
                        // todo 当没传项目id的时候 使用当前用户所有的项目id
                        $directorRole = teamones_request('teamones-im', 'role/find', ['param' => ['filter' => ['code' => TaskService::DIRECTOR_CODE]]])['data'];
                        if (!empty($directorRole)) {
                            $projectMemberUserIdList = model(ProjectMemberModel::class)
                                ->where(['project_id' => $param['filter']['task.project_id'], 'role_id' => $directorRole['id']])
                                ->group('user_id')
                                ->field('user_id')
                                ->column('user_id');
                            if (empty($projectMemberUserIdList)) {
                                throw new LogicException("The project has no director configured", 0);
                            }
                            $res[] = ['task_member.partner' => ['IN', $projectMemberUserIdList]];
                            $this->appendTableList('task_member');
                        }
                    }
                    break;
            }
        }
        return $res;
    }

    /**
     * 查询任务异常情况
     * @param array $taskList
     * @return void
     */
    private function queryTaskAbnormalDetail(array &$taskList)
    {
        $taskIdList = [];
        foreach ($taskList as $task) {
            $taskIdList[] = $task['task']['id'];
        }

        $workOrderList = model(TaskWorkOrderModel::class)
            ->where(['task_id' => ['IN', $taskIdList], 'status' => TaskWorkOrderModel::STATUS_UNTREATED])
            ->field('task_id')
            ->group('task_id')
            ->select();
        $workOrderTaskList = array_column($workOrderList, 'task_id');
        $notStartedStatus = StatusService::getInstance()->getTaskDefaultStatus();
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
        $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
        foreach ($taskList as &$task) {
            $task['abnormal_detail'] = [
                'overdue' => 0,
                'not_started' => false,
                'not_assigned' => false,
                'work_order_not_handled' => false
            ];
            if ($task['task']['status'] == $closedStatus['id']) {
                continue;
            }
            if ($task['task']['step_type'] == TaskModel::STEP_TYPE_STEP) {
                if (in_array($task['task']['id'], $workOrderTaskList)) {
                    $task['abnormal_detail']['work_order_not_handled'] = true;
                }
            }
            // 已经完成或者发布的 不需要检查 分配,未开始的异常
            if (in_array($task['task']['status'], [$doneStatus['id'], $publishStatus['id']])) {
                continue;
            }

            if ($task['task']['step_type'] == TaskModel::STEP_TYPE_STEP) {
                if ($task['task']['plan_end_time'] >= 1 and $task['task']['plan_end_time'] < time() && $task['task']['assign_status'] == TaskModel::ASSIGN_STATUS_DEFAULT) {
                    $task['abnormal_detail']['not_assigned'] = true;
                }
                if ($task['task']['plan_end_time'] >= 1 and $task['task']['plan_end_time'] < time() && $task['task']['status'] == $notStartedStatus['id']) {
                    $task['abnormal_detail']['not_started'] = true;
                }
            }
            if ($task['task']['plan_end_time'] >= 1 and $task['task']['plan_end_time'] < time() && $task['task']['plan_end_time'] < time()) {
                $task['abnormal_detail']['overdue'] = time() - $task['task']['plan_end_time'];
            }
        }
    }

    /**
     * 总进度详情任务统计
     * @param $param
     * @param $tenantId
     * @return array
     */
    public function totalTaskCount($param, $tenantId)
    {

        $categoryIdList = $param['filter']['category_id_list'] ?? [];
        $projectId = $param['filter']['project_id'] ?? null;
        $startTime = $param['filter']['start_time'] ?? 0;
        $endTime = $param['filter']['end_time'] ?? 0;
        $isNowMonthParam = empty($param['filter']['is_now_month']) ? 0 : date('Y', $param['filter']['is_now_month']) . intval(date('m', $param['filter']['is_now_month']));
        $type = $param['filter']['type'] ?? 'step_category';

        //  查询当前项目所有的剧集
        $entityEpisodeData = model(EntityModel::class)
            ->where(['module_id' => module_by_code('episode')['id'], 'project_id' => $projectId])
            ->field('id,name')
            ->select();
        if (empty($entityEpisodeData)) {
            return [];
        }
        $entityEpisodeMap = array_column($entityEpisodeData, null, 'id');
        $entityEpisodeCodeMap = array_column($entityEpisodeData, null, 'name');

        // 查询排期集-资产关联关系
        $planEpisodeRelationData = model(PlanModel::class)
            ->join("task_relation_tag on task_relation_tag.link_module_code in ('show_step_category', 'step_category') and task_relation_tag.task_id = plan.task_id")
            ->where(['plan.scope' => 'single', 'plan.type' => 'step_category'])
            ->where(['plan.start_time' => ["ELT", $endTime], 'plan.end_time' => ["EGT", $startTime]])
            ->where(['plan.project_id' => $projectId])
            ->where(['task_relation_tag.link_id' => ['IN', join(',', $categoryIdList)]])
            ->field("from_unixtime(plan.end_time, '%Y-%m') as yearMonth,from_unixtime(plan.end_time, '%Y') as year,from_unixtime(plan.end_time, '%m') as month,plan.entity_id,task_relation_tag.link_id")
            ->group("yearMonth, entity_id, task_relation_tag.link_id")
            ->select();
        $planEpisodeRelationData = array_map(function ($tmp) use ($entityEpisodeMap) {
            $tmp['episode_name'] = $entityEpisodeMap[$tmp['entity_id']]['name'] ?? null;
            return $tmp;
        }, $planEpisodeRelationData);
        $planEpisodeRelationData = array_filter($planEpisodeRelationData, function ($tmp) {
            return !empty($tmp['episode_name']);
        });

        $planEpisodeRelationData = array_values($planEpisodeRelationData);
        $episodeIds = array_column($planEpisodeRelationData, 'entity_id');

        $list = [];
        if ($type == 'step_category') {
            // 查询环节
            if (!empty($episodeIds)) {

                $episodeTaskData = model(TaskModel::class)
                    ->where(['step_type' => TaskModel::STEP_TYPE_STEP_CATEGORY, 'project_id' => $projectId, 'episode_id' => ['IN', $episodeIds]])
                    ->where(['step_category_id' => ['IN', $categoryIdList]])
                    ->field("count(*) as total_num,count(task.json ->> '$.task_status' = 7 or null) as final_num,episode_id,count(distinct entity_id) as entity_num")
                    ->group('episode_id')
                    ->cache(5)
                    ->select();

                if (!empty($episodeTaskData)) {
                    $list = array_merge($list, $episodeTaskData);
                }

                $categoryIdListIds = join(',', $categoryIdList);
                $toDoEpisodeTaskData = model(TaskModel::class)
                    ->join("(select * from task_relation_tag where link_module_code = 'episode') r_episode on r_episode.task_id = task.id")
                    ->join("(select * from task_relation_tag where link_module_code in ('step_category', 'show_step_category')) r_step_category on r_step_category.task_id = task.id and step_category_id IN ({$categoryIdListIds})")
                    ->field("count(*) as total_num,count(task.json ->> '$.task_status' = 7 or null) as final_num,r_episode.link_id as episode_id,count(entity_id) as entity_num")
                    ->where("task.step_type not in ('step', 'step_category')")
                    ->where(['task.project_id' => $projectId, 'r_episode.link_id' => ['IN', $episodeIds]])
                    ->cache(5)
                    ->group('r_episode.link_id')
                    ->select();
                if (!empty($toDoEpisodeTaskData)) {
                    $list = array_merge($list, $toDoEpisodeTaskData);
                }
            }
        } else {
            // 查询项目成员是导演角色ids
            $tmUserIds = model(ProjectMemberModel::class)->where(['project_id' => $projectId, 'role_code' => 'director'])->column('user_id');
            $tmUserIds = array_values(array_unique($tmUserIds));
            $taskData = model(TaskModel::class)
                ->join('task_member tm on task.id = tm.task_id')
                ->join('plan p on task.id = p.task_id')
                ->where(['tm.partner' => ['IN', join(',', $tmUserIds)]])
                ->where(['p.end_time' => ['BETWEEN', [$startTime, $endTime]],])
                ->where(['p.project_id' => $projectId, 'p.type' => ['IN', ['meeting', 'review']]])
                ->field("count(distinct task.id) as total_num,count(task.json ->> '$.task_status' = 7 or null) as final_num,task.episode_id as episode_id,count(distinct task.id) as entity_num,from_unixtime(task.plan_end_time, '%Y-%m') as yearMonth,from_unixtime(task.plan_end_time, '%Y') as year,from_unixtime(task.plan_end_time, '%m') as month")
                ->group('yearMonth,episode_id')
                ->select();
            $taskData = array_map(function ($tmp) use ($entityEpisodeMap) {
                $tmp['episode_name'] = $entityEpisodeMap[$tmp['episode_id']]['name'] ?? null;
                return $tmp;
            }, $taskData);

            if (!empty($taskData)) {
                $list = $taskData;
                $planEpisodeRelationData = $list;
            }
        }


        // 相同集合并
        $mergeSameEpisodeMap = [];
        $tmpSameEpisodeMap = array_group_by($list, 'episode_id');
        foreach ($tmpSameEpisodeMap as $episodeId => $episodeItem) {
            $totalNum = 0;
            $finalNum = 0;
            $entityNum = 0;
            foreach ($episodeItem as $episodeNumInfo) {
                $totalNum += $episodeNumInfo['total_num'];
                $finalNum += $episodeNumInfo['final_num'];
                $entityNum += $episodeNumInfo['entity_num'];
            }
            $mergeSameEpisodeMap[] = [
                'total_num' => $totalNum,
                'final_num' => $finalNum,
                'episode_id' => $episodeId,
                'entity_num' => $entityNum
            ];
        }

        $episodeTaskFinalInfoMap = array_column($mergeSameEpisodeMap, null, 'episode_id');

        $returnMap = [];
        $listYearGroup = array_group_by($planEpisodeRelationData, 'year');
        foreach ($listYearGroup as $year => $value) {

            $tmpMonthList = [];
            $month = array_group_by($value, 'month');
            foreach ($month as $monthKey => $monthValue) {

                $tmpEpisodeNameList = [];
                $episodeNameListMap = array_group_by($monthValue, 'episode_name');
                $nowMonthEpisodeTotalEntityNum = 0; // 当月前期集的总任务数
                foreach ($episodeNameListMap as $episodeName => $tmpProgressValue) {

                    if (empty($entityEpisodeCodeMap[$episodeName]['id'])) {
                        continue;
                    }
                    $episodeId = $entityEpisodeCodeMap[$episodeName]['id']; // 集id
                    $totalTaskNum = $episodeTaskFinalInfoMap[$episodeId]['total_num'] ?? 0; // 当月当前集总任务数
                    $finalTaskNum = $episodeTaskFinalInfoMap[$episodeId]['final_num'] ?? 0; // 当月当前集完成任务数
                    $entityNum = $episodeTaskFinalInfoMap[$episodeId]['entity_num'] ?? 0; // 当月当前集的实体数
                    $progress = 0;
                    if (!empty($finalTaskNum)) {
                        $progress = ($finalTaskNum / $totalTaskNum) * 100; // 进度
                    }
                    $tmpEpisodeNameList[] = [
                        'progress' => intval($progress), // 进度
                        'episode_id' => $episodeId,
                        'episode_name' => $episodeName, // 集
                        'total_task_num' => $totalTaskNum,
                        'final_task_num' => $finalTaskNum,
                    ];
                    $nowMonthEpisodeTotalEntityNum += $entityNum;
                }
                if ($type == 'role') {
                    $nowMonthEpisodeTotalEntityNum = $monthValue[0]['total_num'] ?? 0;
                }
                $tmpMonthList[intval($monthKey)] = ['episode_name_list' => $tmpEpisodeNameList, 'task_num' => $nowMonthEpisodeTotalEntityNum];
                unset($tmpEpisodeNameList, $totalTaskNum, $finalTaskNum, $nowMonthEpisodeTotalEntityNum);
            }
            $returnMap[$year] = ['year' => $year, 'month' => $tmpMonthList];
            unset($tmpMonthList);
        }

        $yearMonthList = $this->getMonthList($startTime, $endTime);

        // 组织前端初始年月返回列表数据
        $initReturnData = [];
        foreach ($yearMonthList as $year => $monthListItem) {
            $monthList = [];
            foreach ($monthListItem as $month) {
                $month = intval($month);
                $isNowMonth = 'no';
                if ($year . $month == $isNowMonthParam) {
                    $isNowMonth = 'yes';
                }
                $monthList[] = [
                    'is_now_month' => $isNowMonth,
                    'month_name' => $month,
                    'task_num' => $returnMap[$year]['month'][$month]['task_num'] ?? 0,  // 当月总任务数
                    'episode_name_list' => $returnMap[$year]['month'][$month]['episode_name_list'] ?? null,
                ];
            }
            $initReturnData[] = [
                'year' => $year,
                'month' => $monthList
            ];
        }
        return $initReturnData;
    }

    /**
     * 根据开始、结束时间：计算开始、结束时间
     * @param $startTime
     * @param $endTime
     * @return array
     */
    public function getMonthList($startTime, $endTime)
    {
        $startMonth = date('Y-m', $startTime);  //开始日期 年-月
        $endMonth = date('Y-m', $endTime);    //结束日期 年-月
        $dateToPercent = [];
        $currentMonth = $startMonth;
        $t = 0;
        $returnTimes = [];
        do {
            $returnTimes[date('Y', strtotime($currentMonth))][] = date('m', strtotime($currentMonth));
            $dateToPercent[$currentMonth] = 0;
            $t += $dateToPercent[$currentMonth];
            $currentMonth = date("Y-m", strtotime($currentMonth . ' + 1 month'));
        } while (strtotime($currentMonth) <= strtotime($endMonth));
        return $returnTimes;
    }


    /**
     * 获取任务异常详情
     * @param $taskList
     * @return void
     */
    public function getTaskAbnormalDetail(&$taskList)
    {
        if (empty($taskList)) {
            return;
        }
        $taskIdList = array_column($taskList, 'id');
        $workOrderList = model(TaskWorkOrderModel::class)
            ->where(['task_id' => ['IN', $taskIdList], 'status' => TaskWorkOrderModel::STATUS_UNTREATED])
            ->field('task_id, report_content')
            ->group('task_id')
            ->select();
        $workOrderTaskList = array_combine(array_column($workOrderList, 'task_id'), $workOrderList);
        $notStartedStatus = StatusService::getInstance()->getTaskDefaultStatus();
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
        $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
        foreach ($taskList as &$task) {
            $task['abnormal_detail'] = [
                'overdue' => 0,
                'not_started' => false,
                'not_assigned' => false,
                'work_order_not_handled' => false
            ];
            if ($task['status'] == $closedStatus['id']) {
                continue;
            }
            if ($task['step_type'] == TaskModel::STEP_TYPE_STEP) {
                if (isset($workOrderTaskList[$task['id']])) {
                    $task['abnormal_detail']['work_order_not_handled'] = true;
                    $task['abnormal_detail']['work_order_report_content'] = $workOrderTaskList[$task['id']]['report_content'];
                }
            }
            // 已经完成或者发布的 不需要检查 分配,未开始的异常
            if (in_array($task['status'], [$doneStatus['id'], $publishStatus['id']])) {
                continue;
            }

            if ($task['step_type'] == TaskModel::STEP_TYPE_STEP) {
                if ($task['plan_end_time'] >= 1 && $task['plan_end_time'] < time() && $task['assign_status'] == TaskModel::ASSIGN_STATUS_DEFAULT) {
                    $task['abnormal_detail']['not_assigned'] = true;
                }
                if ($task['plan_end_time'] >= 1 && $task['plan_end_time'] < time() && $task['status'] == $notStartedStatus['id']) {
                    $task['abnormal_detail']['not_started'] = true;
                }
            }
            if ($task['plan_end_time'] >= 1 && $task['plan_end_time'] < time() && $task['plan_end_time'] < time()) {
                $task['abnormal_detail']['overdue'] = time() - $task['plan_end_time'];
            }
        }
    }


    /**
     * 今日异常任务
     * @param $param
     * @param $userId
     * @return array
     */
    public function todayAbnormalTask($param, $userId): array
    {
        //未完成,未交付
        $stepCategoryId = $param['step_category_id'] ?? [];
        $departmentId = $param['department_id'] ?? 0;
        // 任务id查询
        $taskIds = $param['filter']['task.id'] ?? [];
        $pureMode = !empty($taskIds);
        $nodeMode = ($param['node_mode'] ?? 'no' === 'yes');

        $startTime = $param['start_time'] ?? strtotime(date('Y-m-d'));
        $endTime = $param['end_time'] ?? strtotime(date('Y-m-d', strtotime('+1 day'))) - 1;
        $timeScope = ['BETWEEN', [$startTime, $endTime]];
        $statusList = StatusService::getInstance()->getList([], "id,name,code,color");
        $statusIdMap = [];
        $statusCodeMap = [];
        foreach ($statusList as $statusItem) {
            $statusIdMap[$statusItem['id']] = $statusItem;
            $statusCodeMap[$statusItem['code']] = $statusItem;
        }

        $delayTaskData = $this->getDealTaskList($param, $userId, $departmentId, $stepCategoryId, $timeScope, $statusCodeMap, $pureMode, $nodeMode);

        $dealTaskList = $delayTaskData['deal_task_list'];
        $departmentUserIds = $delayTaskData['department_user_ids'];

        //拿取该环节,该项目,今日最大的延期单任务
        $delayOrderTaskList = DelayOrderService::getInstance()->getTodoDayMaxDelayOrderTaskList($stepCategoryId, $departmentId, $departmentUserIds, $param['project_id'], $timeScope, $taskIds);
        if (empty($dealTaskList) && empty($delayOrderTaskList)) {
            return [];
        }

        if (isset($param['filter']['task.step_type']) || $param['time_search_type'] == 'overdue_strict') {
            if (empty($dealTaskList)) {
                return [];
            }
            return $this->returnTaskList($delayOrderTaskList, $dealTaskList, $statusCodeMap, $statusIdMap, $startTime, $endTime, []);
        }

        return $this->returnTaskList($delayOrderTaskList, $dealTaskList, $statusCodeMap, $statusIdMap, $startTime, $endTime);
    }


    /**
     * 任务列表(join延期表)
     * @param $param
     * @param $userId
     * @param $departmentId
     * @param $stepCategoryId
     * @param $timeScope
     * @param $statusCodeMap
     * @return array
     */
    public function getDealTaskList($param, $userId, $departmentId, $stepCategoryId, $timeScope, $statusCodeMap, $pureMode = false, $nodeMode = false)
    {
        // 未完成
        $filter = [
            [
                'task.plan_end_time' => $timeScope,
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", [$statusCodeMap['ready_to_publish']['id'], $statusCodeMap['final']['id'], $statusCodeMap['closed']['id']]]
            ],
            [
                'task.plan_delivery_time' => $timeScope,
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", [$statusCodeMap['final']['id'], $statusCodeMap['closed']['id']]]
            ],
            "_logic" => "OR"
        ];


        $dotColumn = "original_plan_time";
        // 应完成
        if (!empty($param['time_search_type']) && $param['time_search_type'] == 'done') {
            $doneFilter = ['task.plan_end_time' => $timeScope];
            if (($param['history'] ?? "no") == "yes") {
                $doneFilter['_logic'] = 'OR';
                $doneFilter[] = [
                    'delay_order_task.original_plan_time' => $timeScope,
                    'manager_confirmed' => 'yes',
                ];
            }
            $filter = [
                $doneFilter,
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'ready_to_publish', 'final'], false, 'id')],
            ];
        }

        // 应交付
        if (!empty($param['time_search_type']) && $param['time_search_type'] == 'delivery') {
            if ($nodeMode && $pureMode) {
                $filter = [];
            } else {
                $dotColumn = "plan_delivery_time";
                $deliveryFilter = ['task.plan_delivery_time' => $timeScope];
                if (($param['history'] ?? "no") == "yes") {
                    $deliveryFilter['_logic'] = 'OR';
                    $deliveryFilter[] = [
                        'delay_order_task.plan_delivery_time' => $timeScope,
                        'manager_confirmed' => 'yes',
                    ];
                }
                $filter = [
                    $deliveryFilter,
                    "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'final'], false, 'id')],
                ];
            }
        }

        // 逾期任务
        $endTime = $param['end_time'] ?? 0;
        if (!empty($param['time_search_type']) && $param['time_search_type'] == 'overdue') {
            $filter = [
                "task.end_time" => 0,
                'task.plan_end_time' => ['LT', $endTime > time() ? time() : $endTime],
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", [$statusCodeMap['closed']['id']]]
            ];
        }

        // 逾期任务
        if (!empty($param['time_search_type']) && $param['time_search_type'] == 'overdue_strict') {
            $filter = [
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NEQ", StatusService::getInstance()->byCode('closed', 'id')],
                "task.plan_end_time" => $timeScope,
                [
                    "_logic" => 'OR',
                    [
                        "_string" => "task.end_time not between 1 and task.plan_end_time"
                    ],
                    "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", StatusService::getInstance()->byCodeMap(['ready_to_publish', 'final'], false, 'id')],
                ]
            ];
        }

        //任务类型限制
        $taskStepTypeScope = TaskModel::STEP_TYPE_TODO_GROUP;
        $taskStepTypeScope[] = TaskModel::STEP_TYPE_STEP;
        $taskStepTypeScope = array_filter($taskStepTypeScope, fn($type) => ($type != 'standard_make_to_do'));
        $taskEntityDb = model(TaskModel::class)->join("entity on entity.id = task.entity_id", "LEFT");
        //部门筛选
        $departmentUserIds = [];
        if (!empty($departmentId)) {
            $du = TenantService::getInstance()->selectDepartmentUser(request()->getTenantId(), [
                'param' => [
                    'filter' => [
                        'department_id' => $departmentId,
                    ]
                ]
            ]);
            $departmentUserIds = array_column($du['rows'], 'saas_user_id');
            if (empty($departmentUserIds)) {
                return [];
            }
            $filter = [
                'task.project_id' => $param['project_id'],
                'task.step_type' => ["IN", $taskStepTypeScope],
                'task_member.partner' => ['IN', implode(',', $departmentUserIds)],
                [
                    $filter
                ]
            ];
            $taskEntityDb = $taskEntityDb->join("task_member on task_member.task_id = task.id");
        }
        //环节筛选
        if (!empty($stepCategoryId)) {
            $filter = [
                'task.project_id' => $param['project_id'],
                'task.step_type' => ["IN", $taskStepTypeScope],
                'task_relation_tag.link_id' => ["IN", $stepCategoryId],
                [
                    $filter
                ]
            ];
            $taskEntityDb = $taskEntityDb->join("task_relation_tag on task_relation_tag.task_id = task.id and task_relation_tag.link_module_code in ('show_step_category','step_category')");
        }
        if (empty($departmentId) && empty($stepCategoryId) && !$pureMode) {
            $filter = [
                'task.project_id' => $param['project_id'],
                'task.step_type' => ["IN", $taskStepTypeScope],
                'task_member.partner' => $userId,
                [
                    $filter
                ]
            ];
            $taskEntityDb = $taskEntityDb->join("task_member on task_member.task_id = task.id");
        }

        $taskEntityDb = $taskEntityDb->join("delay_order_task on delay_order_task.task_id = task.id and delay_order_task.type in ('request_delay', 'today_done') and delay_order_task." . $dotColumn . " between " . $param['start_time'] . ' and ' . $param['end_time'], "LEFT")
            ->join('review_request on delay_order_task.id = review_request.link_id and review_request.module_id = ' . module_by_code('delay_order_task')['id'], 'LEFT');

        if (!empty($param['filter'])) {
            if (empty($filter)) {
                $filter = $param['filter'];
            } else {
                $filter = [$filter, $param['filter']];
            }
        }
        $dealTaskList = $taskEntityDb->where($filter)
            ->field([
                "task.id", "task.name as task_name", "task.project_id", "task.step_type", "task.executor", "task.plan_end_time", "task.episode_id",
                "task.step_category_id", "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status')) as status", "task.plan_delivery_time",
                "entity.initial_episode_code", "entity.showings_number", "entity.name",
                "review_request.is_reviewed",
                "review_request.is_pass",
                "entity.id as entity_id"
            ])->group("task.id")->select();
        return ['deal_task_list' => $dealTaskList ?? [], 'department_user_ids' => $departmentUserIds];
    }

    /**
     * 组织返回数据
     * @param $delayOrderTaskList
     * @param $dealTaskList
     * @param $statusCodeMap
     * @param $statusIdMap
     * @param $startTime
     * @param $endTime
     * @return array
     */
    public function returnTaskList($delayOrderTaskList, $dealTaskList, $statusCodeMap, $statusIdMap, $startTime, $endTime, $delayOrderTaskTaskIdList = null)
    {
        $delayOrderTaskMap = [];
        //通过延期单id拿到审核内容
        $delayOrderTaskIds = [];
        $delayOrderTaskTaskIds = is_array($delayOrderTaskTaskIdList) ? $delayOrderTaskTaskIdList : [];
        if (!empty($delayOrderTaskList)) {
            foreach ($delayOrderTaskList as $delayOrderTaskItem) {
                $delayOrderTaskIds[$delayOrderTaskItem['id']] = $delayOrderTaskItem['id'];
                $delayOrderTaskMap[$delayOrderTaskItem['task_id']] = $delayOrderTaskItem;
                if (is_null($delayOrderTaskTaskIdList)) {
                    $delayOrderTaskTaskIds[$delayOrderTaskItem['task_id']] = $delayOrderTaskItem['task_id'];
                }
            }
        }
        $delayOrderTaskTaskMap = [];
        if (!empty($delayOrderTaskTaskIds)) {
            $delayOrderTaskTaskList = model(TaskModel::class)
                ->join("entity on entity.id = task.entity_id", "LEFT")
                ->where(['task.id' => ["IN", $delayOrderTaskTaskIds]])
                ->field([
                    "task.id", "task.name as task_name", "task.project_id", "task.episode_id", "task.step_type", "task.executor", "task.plan_end_time",
                    "task.step_category_id", "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status')) as status", "task.plan_delivery_time",
                    "entity.initial_episode_code", "entity.showings_number", "entity.name", "entity.id as entity_id",
                ])
                ->select();
            $delayOrderTaskTaskMap = array_column($delayOrderTaskTaskList, null, 'id');
        }

        //合并任务列表
        $taskList = array_values(array_column($dealTaskList, null, 'id') + $delayOrderTaskTaskMap);
        $taskIdList = array_column($taskList, 'id');
        $workOrderList = model(TaskWorkOrderModel::class)
            ->where(['task_id' => ['IN', $taskIdList], 'status' => TaskWorkOrderModel::STATUS_UNTREATED])
            ->field('task_id, report_content')
            ->select();
        $workOrderTaskList = array_column($workOrderList, null, 'task_id');

        $userIdList = [];
        $stepCategoryIds = [];
        $todoTaskIds = [];
        foreach ($taskList as $taskItem) {
            if ($taskItem['step_type'] == TaskModel::STEP_TYPE_STEP) {
                $userIdList[$taskItem['executor']] = $taskItem['executor'];
                $stepCategoryIds[$taskItem['step_category_id']] = $taskItem['step_category_id'];
            } else {
                $todoTaskIds[] = $taskItem['id'];
            }
        }

        //待办的需要获取环节id和集id
        $todoTaskMap = [];
        $episodeCodeMap = [];
        if (!empty($todoTaskIds)) {
            $taskRelationTagList = model(TaskRelationTagModel::class)
                ->where([
                    'task_id' => ["IN", $todoTaskIds],
                    'link_module_code' => ["IN", ["show_step_category", "step_category", "episode"]]
                ])
                ->field("task_id,link_module_code,link_id")
                ->select();

            $todoTaskEpisodeIds = [];
            foreach ($taskRelationTagList as $taskRelationTagItem) {
                if (in_array($taskRelationTagItem['link_module_code'], ['step_category', 'show_step_category'])) {
                    if (!empty($stepCategoryId)) {
                        if (in_array($taskRelationTagItem['link_id'], $stepCategoryId)) {
                            $todoTaskMap[$taskRelationTagItem['task_id']]['step_category_id'] = $taskRelationTagItem['link_id'];
                            $stepCategoryIds[$taskRelationTagItem['link_id']] = $taskRelationTagItem['link_id'];
                        }
                    } else {
                        $todoTaskMap[$taskRelationTagItem['task_id']]['step_category_id'] = $taskRelationTagItem['link_id'];
                        $stepCategoryIds[$taskRelationTagItem['link_id']] = $taskRelationTagItem['link_id'];
                    }
                } else {
                    $todoTaskMap[$taskRelationTagItem['task_id']]['episode_id'] = $taskRelationTagItem['link_id'];
                    $todoTaskEpisodeIds[$taskRelationTagItem['link_id']] = $taskRelationTagItem['link_id'];
                }
            }

            //剧集code查询
            if (!empty($todoTaskEpisodeIds)) {
                $episodeList = model(EntityModel::class)->where(['id' => ["IN", $todoTaskEpisodeIds]])->select();
                $episodeCodeMap = array_column($episodeList, 'code', 'id');
            }

            $taskMemberList = model(TaskMemberModel::class)
                ->where(['task_id' => ['IN', implode(',', $todoTaskIds)]])
                ->where(['partner' => ['GT', 0]])
                ->select();
            foreach ($taskMemberList as $taskMember) {
                if ($taskMember['user_id'] > 0) {
                    $userIdList[$taskMember['user_id']] = $taskMember['user_id'];
                }
                if ($taskMember['partner'] > 0) {
                    $userIdList[$taskMember['partner']] = $taskMember['partner'];
                }
            }
            $taskMemberList = array_group_by($taskMemberList, 'task_id');
        }

        //获取环节名
        $stepCategoryMap = [];
        if (!empty($stepCategoryIds)) {
            $stepCategoryList = model(StepCategoryModel::class)->where(["id" => ["IN", array_values($stepCategoryIds)]])->field("id,name,code")->select();
            $stepCategoryMap = array_column($stepCategoryList, null, 'id');
        }

        //获取执行人名
        $userList = [];
        if (!empty($userIdList)) {
            $executorList = model(UserModel::class)->where(['id' => ["IN", array_values($userIdList)]])->field("id,name,avatar")->select();
            $userList = array_column($executorList, null, 'id');
        }

        //获取审核内容
        $reviewRequestMap = [];
        if (!empty($delayOrderTaskIds)) {
            $delayOrderTaskIds = array_values($delayOrderTaskIds);
            $reviewRequestList = model(ReviewRequestModel::class)
                ->where([
                    'link_id' => ["IN", $delayOrderTaskIds],
                    'module_id' => module_by_code("delay_order_task")['id']
                ])->field("id,link_id,is_reviewed,is_pass")->select();
            $reviewRequestMap = array_column($reviewRequestList, null, 'link_id');
        }

        // 获取实体信息
        $entityField = [
            "JSON_UNQUOTE(JSON_EXTRACT(entity.`json`, CONCAT('$.',module.code, '_', 'grade'))) as grade",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.`json`, CONCAT('$.',module.code, '_', 'category'))) as category",
            "director_star",
            "key_shot"
        ];
        $entityIds = array_column($taskList, 'entity_id');
        $entityList = model(EntityModel::class)
            ->join('module on module.id = entity.module_id', 'LEFT')
            ->field($entityField)
            ->where(['entity.id' => ['IN', $entityIds]])
            ->select();
        if (empty($entityList)) {
            $entityMap = array_column($entityList, null, 'id');
        }

        //未处理的任务
        foreach ($taskList as &$taskItem) {
            if (isset($workOrderTaskList[$taskItem['id']])) {
                $taskItem['work_order_report_content'] = $workOrderTaskList[$taskItem['id']]['report_content'];
            }
            //异常情况判定
            $taskItem['is_deal'] = isset($delayOrderTaskMap[$taskItem['id']]);
            $taskItem['type'] = null;
            $taskItem['delay_review_progress'] = null;
            //待办的需要补充 集 环节
            if ($taskItem['step_type'] == TaskModel::STEP_TYPE_STEP) {
                $taskItem['task_member_list'] = [[
                    'id' => $taskItem['id'],
                    'status' => $taskItem['status'] != 7 ? 1 : 7,
                    'user_info' => $userList[$taskItem['executor']] ?? null,
                    'type' => 'executor',
                ]];
            } else {
                $taskItem['step_category_id'] = $todoTaskMap[$taskItem['id']]['step_category_id'] ?? 0;
                $taskItem['episode_id'] = $todoTaskMap[$taskItem['id']]['episode_id'] ?? 0;
                $taskItem['initial_episode_code'] = $episodeCodeMap[$taskItem['episode_id']] ?? '';
                $taskItem['task_member_list'] = $taskMemberList[$taskItem['id']] ?? [];
                foreach ($taskItem['task_member_list'] as &$taskMember) {
                    if ($taskMember['partner'] > 0) {
                        $taskMember['user_info'] = $userList[$taskMember['partner']] ?? null;
                    }
                    $taskMember['type'] = $taskMember['user_id'] > 0 ? 'executor' : 'partner';
                }
            }

            //如有延期,先读取延期单内的异常状态
            if ($taskItem['is_deal']) {
                //当前延期任务
                $currentDelayOrderTask = $delayOrderTaskMap[$taskItem['id']];
                $taskItem['type'] = $delayOrderTaskMap[$taskItem['id']]['type'];
                $taskItem['delay_info'] = $delayOrderTaskMap[$taskItem['id']];
                $taskItem['abnormal_info'] = $currentDelayOrderTask['abnormal_info'];
                //延期审核进度
                $taskItem['delay_review_progress'] = $reviewRequestMap[$delayOrderTaskMap[$taskItem['id']]['id']] ?? null;
            } else {
                //是否当前时间端内未完成
                if ($taskItem["plan_end_time"] >= $startTime && $taskItem["plan_end_time"] <= $endTime &&
                    !in_array($taskItem['status'], [$statusCodeMap['ready_to_publish']['id'], $statusCodeMap['final']['id']])) {
                    $taskItem['abnormal_info'] = "not_done";
                } elseif ($taskItem["plan_delivery_time"] >= $startTime && $taskItem["plan_delivery_time"] <= $endTime && $taskItem['status'] != $statusCodeMap['final']['id']) { //是否是当前时间段内未交付
                    $taskItem['abnormal_info'] = "not_delivery";
                }
            }
            $taskItem['step_category'] = $stepCategoryMap[$taskItem['step_category_id']] ?? null;
            $taskItem['status'] = $statusIdMap[$taskItem['status']] ?? null;
            $taskItem['grade'] = $entityMap[$taskItem['entity_id']]['grade'] ?? null;
            $taskItem['category'] = $entityMap[$taskItem['entity_id']]['category'] ?? null;
        }

        return $taskList;
    }

    /**
     * 查询任务列表总数
     * @param array $tableList
     * @param array $filter
     * @param $extraFilter
     * @param $sourceFilter
     * @return RelationModel
     * @throws \Exception
     */
    private function getTaskListTotal(array $tableList, array $filter, $extraFilter, $sourceFilter)
    {
        $timeSearchType = $sourceFilter['time_search_type'] ?? 'done';
        $timeSearch = $sourceFilter['time_search'] ?? [];
        $todoStepCategoryId = $sourceFilter['todo_step_category_id'] ?? $sourceFilter['todo_step_category_id_list'] ?? null;
        $projectId = $sourceFilter['project_id'] ?? $sourceFilter['task.project_id'] ?? 0;

        if (empty($timeSearch)) {
            return $this->getTaskListQuery($tableList)
                ->where($filter)
                ->where($extraFilter)
                ->count("distinct task.id");
        }
        $delayOrderTaskWhere = [];
        if (!empty($todoStepCategoryId)) {
            $delayOrderTaskWhere['delay_order_task.step_category_id'] = $todoStepCategoryId;
        }
        if (!empty($projectId)) {
            $delayOrderTaskWhere['delay_order_task.project_id'] = $projectId;
        }
        switch ($timeSearchType) {
            case 'history_done':
                $taskQuery = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->where(['task.plan_end_time' => ["BETWEEN", $timeSearch],])
                    ->field('task.id')
                    ->buildSql();
                $delayOrderTaskQ = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->join('delay_order_task on task.id = delay_order_task.task_id')
                    ->where([
                        'delay_order_task.manager_confirmed' => 'yes',
                        'delay_order_task.original_plan_time' => ['BETWEEN', $timeSearch],
                    ])
                    ->where($delayOrderTaskWhere)
                    ->field('task.id')
                    ->buildSql();
                $unionTable = model(TaskModel::class)->table($taskQuery . ' regular_task')
                    ->union($delayOrderTaskQ)->field('id')->buildSql();
                return model(TaskModel::class)->table($unionTable . ' union_table')->count('distinct id');
            case 'history_delivery':
                $taskQuery = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->where(['task.plan_delivery_time' => ["BETWEEN", $timeSearch],])
                    ->field('task.id')
                    ->buildSql();
                $delayOrderTaskQ = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->join('delay_order_task on task.id = delay_order_task.task_id')
                    ->where([
                        'delay_order_task.manager_confirmed' => 'yes',
                        'delay_order_task.plan_delivery_time' => ['BETWEEN', $timeSearch],
                    ])
                    ->where($delayOrderTaskWhere)
                    ->field('task.id')
                    ->buildSql();
                $unionTable = model(TaskModel::class)->table($taskQuery . ' regular_task')
                    ->union($delayOrderTaskQ)->field('id')->buildSql();
                return model(TaskModel::class)->table($unionTable . ' union_table')->count('distinct id');
            default:
                return $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->count("distinct task.id");
        }
    }

    /**
     * 查询任务列表
     * @param array $tableList
     * @param array $filter
     * @param $extraFilter
     * @param $sourceFilter
     * @param $page
     * @param $order
     * @return array|false|mixed|string
     * @throws \Exception
     */
    private function getTaskListIdList(array $tableList, array $filter, $extraFilter, $sourceFilter, $page, $order)
    {
        $timeSearchType = $sourceFilter['time_search_type'] ?? 'done';
        $timeSearch = $sourceFilter['time_search'] ?? [];
        $todoStepCategoryId = $sourceFilter['todo_step_category_id'] ?? $sourceFilter['todo_step_category_id_list'] ?? null;
        $projectId = $sourceFilter['project_id'] ?? $sourceFilter['task.project_id'] ?? 0;

        if (empty($timeSearch)) {
            return $this->getTaskListQuery($tableList)
                ->where($filter)
                ->where($extraFilter)
                ->page($page[0], $page[1])
                ->field('task.id')
                ->group('task.id')
                ->order($order)
                ->select();
        }
        $delayOrderTaskWhere = [];
        if (!empty($todoStepCategoryId)) {
            $delayOrderTaskWhere['delay_order_task.step_category_id'] = $todoStepCategoryId;
        }
        if (!empty($projectId)) {
            $delayOrderTaskWhere['delay_order_task.project_id'] = $projectId;
        }

        switch ($timeSearchType) {
            case 'history_done':
                $taskQuery = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->where(['task.plan_end_time' => ["BETWEEN", $timeSearch],])
                    ->field('task.*')
                    ->buildSql();
                $delayOrderTaskQ = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->join('delay_order_task on task.id = delay_order_task.task_id')
                    ->where([
                        'delay_order_task.manager_confirmed' => 'yes',
                        'delay_order_task.original_plan_time' => ['BETWEEN', $timeSearch],
                    ])
                    ->where($delayOrderTaskWhere)
                    ->field('task.*')
                    ->buildSql();
                $unionTable = model(TaskModel::class)
                    ->table($taskQuery . ' regular_task')
                    ->union($delayOrderTaskQ)
                    ->field('*')
                    ->buildSql();
                return model(TaskModel::class)
                    ->table($unionTable . ' task')
                    ->order($order)
                    ->page($page[0], $page[1])
                    ->field('task.id')
                    ->group('task.id')
                    ->select();
            case 'history_delivery':
                $taskQuery = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->where(['task.plan_delivery_time' => ["BETWEEN", $timeSearch],])
                    ->field('task.*')
                    ->buildSql();
                $delayOrderTaskQ = $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->join('delay_order_task on task.id = delay_order_task.task_id')
                    ->where([
                        'delay_order_task.manager_confirmed' => 'yes',
                        'delay_order_task.plan_delivery_time' => ['BETWEEN', $timeSearch],
                    ])
                    ->where($delayOrderTaskWhere)
                    ->field('task.*')
                    ->buildSql();
                $unionTable = model(TaskModel::class)
                    ->table($taskQuery . ' regular_task')
                    ->union($delayOrderTaskQ)
                    ->field('*')
                    ->buildSql();
                return model(TaskModel::class)
                    ->table($unionTable . ' task')
                    ->order($order)
                    ->page($page[0], $page[1])
                    ->field('task.id')
                    ->group('task.id')
                    ->select();
            default:
                return $this->getTaskListQuery($tableList)
                    ->where($filter)
                    ->where($extraFilter)
                    ->page($page[0], $page[1])
                    ->field('task.id')
                    ->group('task.id')
                    ->order($order)
                    ->select();
        }


    }
}

